package haust;

import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;


/*
 *  4D Vector Class
 *  
 *  Can be used as a 4D vector with xyzw components or a rgba color vector
 */
public class Vec4
{
	/**
	 * Sets all values (xyzw) to 0.0f
	 */
	Vec4()
	{
		values.put(0, 0.0f);
		values.put(1, 0.0f);
		values.put(2, 0.0f);
		values.put(3, 0.0f);
	}
	
	/**
	 * 
	 * @param x
	 * @param y
	 * @param z
	 * @param w
	 */
	Vec4(float x, float y, float z, float w)
	{
		values.put(0, x);
		values.put(1, y);
		values.put(2, z);
		values.put(3, w);
	}
	
	
	/**
	 * 
	 * @param v
	 */
	Vec4( Vec4 v )
	{
		Set(v);
	}
	
	
	/**
	 * Multiply v1 and v2 and store it in this instance
	 * This is quaternion multiplication, not the dot product.
	 * @param v1
	 * @param v2
	 */

	void multiply( Vec4 v1, Vec4 v2 )
	{
		/*
		x = w1x2 + x1w2 + y1z2 - z1y2
		y = w1y2 + y1w2 + z1x2 - x1z2
		z = w1z2 + z1w2 + x1y2 - y1x2
		w = w1w2 - x1x2 - y1y2 - z1z2
		*/	
		setX(v1.getW()*v2.getX() + v1.getX()*v2.getW() + v1.getY()*v2.getZ() - v1.getZ()*v2.getY());
		setY(v1.getW()*v2.getY() + v1.getY()*v2.getW() + v1.getZ()*v2.getX() - v1.getX()*v2.getZ());
		setZ(v1.getW()*v2.getZ() + v1.getZ()*v2.getW() + v1.getX()*v2.getY() - v1.getY()*v2.getX());
		setW(v1.getW()*v2.getW() - v1.getX()*v2.getX() - v1.getY()*v2.getY() - v1.getZ()*v2.getZ());
	}
	
	/**
	 * Rotate this vector around an arbitrary vector
	 * 
	 * @param radians
	 * @param x
	 * @param y
	 * @param z
	 */
	void rotate(float radians, float x, float y, float z)
	{
		float sinAngle = (float) Math.sin(radians*0.5);
		
		setX( x*sinAngle );
		setY( y*sinAngle );
		setZ( z*sinAngle );
		setW( (float) Math.cos( radians *0.5 ) );
	}
	
	/**
	 * Conjugate is a negation of the x,y,z but w stays the same
	 */
	void conjugate()
	{
		setX( -getX() );
		setY( -getY() );
		setZ( -getZ() );
		//w = w
	}
	
	float getX() { return values.get(0); }
	float getY() { return values.get(1); }
	float getZ() { return values.get(2); }
	float getW() { return values.get(3); }
	FloatBuffer get()  { return values; }
	void setX(float val)  { values.put(0, val); }
	void setY(float val)  { values.put(1, val); }
	void setZ(float val)  { values.put(2, val); }
	void setW(float val)  { values.put(3, val); }
	
	/**
	 * 
	 * @param v Vector to copy and store in this instance
	 */
	void Set(Vec4 v) 
	{
		values.put(0, v.getX());
		values.put(1, v.getY());
		values.put(2, v.getZ());
		values.put(3, v.getW());
	}
	
	
	private FloatBuffer values = BufferUtils.createFloatBuffer(4);
}